﻿using Shake.Framework.Infrastructure;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;

namespace Shake.Framework.Utility
{
    public class FeatureUtil
    {
        public static IEnumerable<Assembly> _moduleAssembly { get; private set; }

        public static IEnumerable<string> GetModuleBinPaths()
        {
            var results = new List<string>();
            var moduleRootFullPaths = FeatureUtil.GetModuleRootPath();
            var hostBinFullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins");

            foreach (var moduleRootFullPath in moduleRootFullPaths)
            {
                DirectoryInfo info = new DirectoryInfo(moduleRootFullPath);
                var path = Path.Combine(hostBinFullPath, info.Name, "bin");
                if (Directory.Exists(path))
                {
                    results.Add(path);
                }
            }
            return results;
        }

        /// <summary>
        /// 获取模块的根目录路径
        /// </summary>
        /// <param name="relativePath"></param>
        /// <returns></returns>
        public static List<string> GetModuleRootPath(bool relativePath = false)
        {
            string moduleFullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins");
            var results = Directory.GetDirectories(moduleFullPath).ToList();
            if (relativePath)
            {
                for (int i = 0; i < results.Count; i++)
                {
                    results[i] = results[i].Replace(AppDomain.CurrentDomain.BaseDirectory, string.Empty);
                }
            }
            return results;
        }

        public static IEnumerable<Assembly> GetFeatureAssembly()
        {
            if (_moduleAssembly == null)
            {
                var moduleRootFullPaths = FeatureUtil.GetModuleRootPath();
                var hostBinFullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin");
                List<Assembly> results = new List<Assembly>();
                foreach (var moduleRootFullPath in moduleRootFullPaths)
                {
                    DirectoryInfo info = new DirectoryInfo(moduleRootFullPath);
                    var path = Path.Combine(hostBinFullPath, info.Name + ".dll");
                    if (File.Exists(path))
                    {
                        var result = Assembly.LoadFrom(path);
                        results.Add(result);
                    }
                }

                _moduleAssembly = results;
            }
            return _moduleAssembly;
        }

        public static IFeature TryGetFeature(Assembly assembly)
        {
            var featureTypes = assembly.ExportedTypes.Where(t => t.GetInterfaces().Any(s => s == typeof(IFeature)))
                .Select(t => t.Assembly.CreateInstance(t.FullName));
            var result = featureTypes.Cast<IFeature>().FirstOrDefault();
            return result;
            //return featureTypes.ToList().FirstOrDefault();
        }

        public static IEnumerable<Type> GetControllers()
        {
            var assemblies = GetFeatureAssembly();
            var results = new List<Type>();
            foreach (var assembly in assemblies)
            {
                var controllers = assembly.ExportedTypes.Where(t => t.BaseType == typeof(Controller)).ToList();
                if (controllers.Any())
                {
                    results.AddRange(controllers);
                }
            }
            return results;
        }
    }
}
